// 缓存管理工具

interface CacheItem<T> {
  data: T;
  timestamp: number;
  expiry?: number;
}

interface CacheOptions {
  expiry?: number; // 过期时间（毫秒）
  storage?: "localStorage" | "sessionStorage" | "memory";
}

class CacheManager {
  private memoryCache = new Map<string, CacheItem<any>>();
  private defaultExpiry = 5 * 60 * 1000; // 5分钟

  /**
   * 设置缓存
   */
  set<T>(key: string, data: T, options: CacheOptions = {}): void {
    const { expiry = this.defaultExpiry, storage = "memory" } = options;

    const cacheItem: CacheItem<T> = {
      data,
      timestamp: Date.now(),
      expiry,
    };

    switch (storage) {
      case "localStorage":
        try {
          localStorage.setItem(key, JSON.stringify(cacheItem));
        } catch (error) {
          console.warn("Failed to set localStorage cache:", error);
          this.memoryCache.set(key, cacheItem);
        }
        break;

      case "sessionStorage":
        try {
          sessionStorage.setItem(key, JSON.stringify(cacheItem));
        } catch (error) {
          console.warn("Failed to set sessionStorage cache:", error);
          this.memoryCache.set(key, cacheItem);
        }
        break;

      case "memory":
      default:
        this.memoryCache.set(key, cacheItem);
        break;
    }
  }

  /**
   * 获取缓存
   */
  get<T>(
    key: string,
    storage: "localStorage" | "sessionStorage" | "memory" = "memory"
  ): T | null {
    let cacheItem: CacheItem<T> | null = null;

    switch (storage) {
      case "localStorage":
        try {
          const stored = localStorage.getItem(key);
          if (stored) {
            cacheItem = JSON.parse(stored);
          }
        } catch (error) {
          console.warn("Failed to get localStorage cache:", error);
        }
        break;

      case "sessionStorage":
        try {
          const stored = sessionStorage.getItem(key);
          if (stored) {
            cacheItem = JSON.parse(stored);
          }
        } catch (error) {
          console.warn("Failed to get sessionStorage cache:", error);
        }
        break;

      case "memory":
      default:
        cacheItem = this.memoryCache.get(key) || null;
        break;
    }

    if (!cacheItem) {
      return null;
    }

    // 检查是否过期
    if (
      cacheItem.expiry &&
      Date.now() - cacheItem.timestamp > cacheItem.expiry
    ) {
      this.delete(key, storage);
      return null;
    }

    return cacheItem.data;
  }

  /**
   * 删除缓存
   */
  delete(
    key: string,
    storage: "localStorage" | "sessionStorage" | "memory" = "memory"
  ): void {
    switch (storage) {
      case "localStorage":
        localStorage.removeItem(key);
        break;

      case "sessionStorage":
        sessionStorage.removeItem(key);
        break;

      case "memory":
      default:
        this.memoryCache.delete(key);
        break;
    }
  }

  /**
   * 清除所有缓存
   */
  clear(storage?: "localStorage" | "sessionStorage" | "memory"): void {
    if (!storage) {
      // 清除所有存储
      this.memoryCache.clear();
      localStorage.clear();
      sessionStorage.clear();
      return;
    }

    switch (storage) {
      case "localStorage":
        localStorage.clear();
        break;

      case "sessionStorage":
        sessionStorage.clear();
        break;

      case "memory":
        this.memoryCache.clear();
        break;
    }
  }

  /**
   * 清除过期缓存
   */
  clearExpired(): void {
    // 清除内存中的过期缓存
    for (const [key, item] of this.memoryCache.entries()) {
      if (item.expiry && Date.now() - item.timestamp > item.expiry) {
        this.memoryCache.delete(key);
      }
    }

    // 清除localStorage中的过期缓存
    this.clearExpiredFromStorage("localStorage");

    // 清除sessionStorage中的过期缓存
    this.clearExpiredFromStorage("sessionStorage");
  }

  private clearExpiredFromStorage(
    storage: "localStorage" | "sessionStorage"
  ): void {
    const storageObj =
      storage === "localStorage" ? localStorage : sessionStorage;
    const keysToRemove: string[] = [];

    for (let i = 0; i < storageObj.length; i++) {
      const key = storageObj.key(i);
      if (key) {
        try {
          const item = JSON.parse(storageObj.getItem(key) || "");
          if (item.expiry && Date.now() - item.timestamp > item.expiry) {
            keysToRemove.push(key);
          }
        } catch (error) {
          // 忽略解析错误
        }
      }
    }

    keysToRemove.forEach((key) => storageObj.removeItem(key));
  }

  /**
   * 获取缓存统计信息
   */
  getStats(): {
    memorySize: number;
    localStorageSize: number;
    sessionStorageSize: number;
  } {
    const memorySize = this.memoryCache.size;

    let localStorageSize = 0;
    let sessionStorageSize = 0;

    try {
      localStorageSize = localStorage.length;
    } catch (error) {
      // 忽略错误
    }

    try {
      sessionStorageSize = sessionStorage.length;
    } catch (error) {
      // 忽略错误
    }

    return {
      memorySize,
      localStorageSize,
      sessionStorageSize,
    };
  }
}

// 创建全局缓存实例
export const cache = new CacheManager();

// API响应缓存装饰器
export function cached<T extends (...args: any[]) => Promise<any>>(
  options: CacheOptions & { keyGenerator?: (...args: any[]) => string } = {}
) {
  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    const originalMethod = descriptor.value;

    descriptor.value = async function (...args: any[]) {
      const {
        keyGenerator = (...args: any[]) =>
          `${propertyKey}_${JSON.stringify(args)}`,
        ...cacheOptions
      } = options;

      const cacheKey = keyGenerator(...args);

      // 尝试从缓存获取
      const cached = cache.get(cacheKey, cacheOptions.storage);
      if (cached !== null) {
        return cached;
      }

      // 执行原方法
      const result = await originalMethod.apply(this, args);

      // 缓存结果
      cache.set(cacheKey, result, cacheOptions);

      return result;
    };

    return descriptor;
  };
}

// 图片缓存
export class ImageCache {
  private static cache = new Map<string, HTMLImageElement>();
  private static loading = new Set<string>();

  static async load(src: string): Promise<HTMLImageElement> {
    // 如果已缓存，直接返回
    if (this.cache.has(src)) {
      return this.cache.get(src)!;
    }

    // 如果正在加载，等待加载完成
    if (this.loading.has(src)) {
      return new Promise((resolve, reject) => {
        const checkLoaded = () => {
          if (this.cache.has(src)) {
            resolve(this.cache.get(src)!);
          } else if (!this.loading.has(src)) {
            reject(new Error("Image loading failed"));
          } else {
            setTimeout(checkLoaded, 50);
          }
        };
        checkLoaded();
      });
    }

    // 开始加载
    this.loading.add(src);

    return new Promise((resolve, reject) => {
      const img = new Image();

      img.onload = () => {
        this.cache.set(src, img);
        this.loading.delete(src);
        resolve(img);
      };

      img.onerror = () => {
        this.loading.delete(src);
        reject(new Error(`Failed to load image: ${src}`));
      };

      img.src = src;
    });
  }

  static preload(sources: string[]): Promise<HTMLImageElement[]> {
    return Promise.all(sources.map((src) => this.load(src)));
  }

  static clear(): void {
    this.cache.clear();
    this.loading.clear();
  }

  static getSize(): number {
    return this.cache.size;
  }
}

// 定期清理过期缓存
setInterval(() => {
  cache.clearExpired();
}, 10 * 60 * 1000); // 每10分钟清理一次

export default cache;
